package com.jyw.business.de.service.impl;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.jyw.business.de.constant.*;
import com.jyw.business.de.domain.*;
import com.jyw.business.de.domain.dto.web.*;
import com.jyw.business.de.domain.vo.web.*;
import com.jyw.business.de.service.*;
import com.jyw.common.annotation.DataScope;
import com.jyw.common.constant.SysDictTypeConstant;
import com.jyw.common.core.domain.entity.SysDictData;
import com.jyw.common.core.domain.model.SimpleDto;
import com.jyw.common.core.page.BasePage;
import com.jyw.common.exception.ServiceException;
import com.jyw.common.utils.DateUtils;
import com.jyw.common.utils.DictUtils;
import com.jyw.common.utils.PageUtils;
import com.jyw.common.utils.SecurityUtils;
import com.jyw.system.service.ISysSeatService;
import com.jyw.system.utils.ConversionUtil;
import com.jyw.system.utils.FileUtils;
import org.springframework.stereotype.Service;
import com.jyw.business.de.mapper.DeDemandInfoMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;

/**
 * 需求-需求信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-02-19
 */
@Service
public class DeDemandInfoServiceImpl extends ServiceImpl<DeDemandInfoMapper,DeDemandInfo> implements IDeDemandInfoService
{
    @Resource
    private DeDemandInfoMapper deDemandInfoMapper;

    @Resource
    private IDeDemandSubService deDemandSubService;

    @Resource
    private IDeDemandProcessService processService;

    @Resource
    private IDeDemandAllocationService allocationService;

    @Resource
    private ISysSeatService seatService;

    @Resource
    private IDeDemandResearchService researchService;

    @Resource
    private IDeTaskInfoService taskInfoService;

    @Resource
    private IDeDemandAnalyzeService analyzeService;

    @Resource
    private IDeDemandRatingService ratingService;

    @Resource
    private IDeDemandProjectAuditService projectAuditService;

    @Resource
    private IDeDemandMakeService makeService;

    /**
     * 查询需求-需求信息
     * 
     * @param id 需求-需求信息主键
     * @return 需求-需求信息
     */
    @Override
    public DeDemandInfo selectDeDemandInfoById(Long id)
    {
        return deDemandInfoMapper.selectDeDemandInfoById(id);
    }

    /**
     * 查询需求-需求信息列表
     * 
     * @param deDemandInfo 需求-需求信息
     * @return 需求-需求信息
     */
    @Override
    public List<DeDemandInfo> selectDeDemandInfoList(DeDemandInfo deDemandInfo)
    {
        return deDemandInfoMapper.selectDeDemandInfoList(deDemandInfo);
    }

    /**
     * 新增需求-需求信息
     * 
     * @param dto 需求-需求信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertDeDemandInfo(DemandInfoAddDto dto)
    {
        DeDemandInfo info = dto.buildDemand();
        //设置创建信息
        info.setCreateTime(DateUtils.getNowDate());
        info.setCreateUser(SecurityUtils.getUserId());
        //todo 设置编码
        info.setDemandCode(generateCode());

        if(dto.isSubmit()){
            //设置状态为待分配
            info.setDemandState(DemandStateConstant.ALLOCATION);
            info.setWaitAllocationTime(DateUtils.getNowDate());
        }else{
            //设置状态为待提交
            info.setDemandState(DemandStateConstant.WAIT_SUBMIT);
        }
        int i = deDemandInfoMapper.insertDeDemandInfo(info);
        //构建需求提出科室
        List<DeDemandSub> deDemandSubs = dto.buildSub(info);
        deDemandSubService.saveBatch(deDemandSubs);
        processService.saveProcess(info.getId(), DemandProcessConstant.DEMAND,info);
        //判断状态是否为待分配那么调用自动分配功能
        if(info.getDemandState().equals(DemandStateConstant.ALLOCATION)){
            allocationService.autoAllocation(info.getId());
        }
        return i;
    }

    /**
     * todo 需求编码生成(需要产品确认)
     * @return
     */
    private String generateCode(){
      return null;
    };
    /**
     * 修改需求-需求信息
     * 
     * @param dto 需求-需求信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateDeDemandInfo(DemandInfoEditDto dto)
    {
        //查询需求
        DeDemandInfo data = getById(dto.getId());
        if(!DemandStateConstant.WAIT_SUBMIT.equals(data.getDemandState())){
            throw new ServiceException("待提交才能编辑需求");
        }
        DeDemandInfo info = dto.buildDemand();
        if(dto.isSubmit()){
            //设置状态为待分配
            info.setDemandState(DemandStateConstant.ALLOCATION);
            info.setWaitAllocationTime(DateUtils.getNowDate());
        }else{
            //设置状态为待提交
            info.setDemandState(DemandStateConstant.WAIT_SUBMIT);
        }
        //修改需求
        updateById(info);
        //删除提出科室
        deDemandSubService.lambdaUpdate().eq(DeDemandSub::getDemandId,dto.getId()).remove();
        //重写提出科室
        deDemandSubService.saveBatch(dto.buildSub());

        //判断状态是否为待分配那么调用自动分配功能
        if(info.getDemandState().equals(DemandStateConstant.ALLOCATION)){
            allocationService.autoAllocation(info.getId());
        }
        return 1;
    }

    /**
     * 批量删除需求-需求信息
     * 
     * @param ids 需要删除的需求-需求信息主键
     * @return 结果
     */
    @Override
    public int deleteDeDemandInfoByIds(Long[] ids)
    {
        return deDemandInfoMapper.deleteDeDemandInfoByIds(ids);
    }

    /**
     * 删除需求-需求信息信息
     * 
     * @param id 需求-需求信息主键
     * @return 结果
     */
    @Override
    public int deleteDeDemandInfoById(Long id)
    {
        return deDemandInfoMapper.deleteDeDemandInfoById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void acceptDemand(Long demandId) {
        //查询需求
        DeDemandInfo info = getById(demandId);
        if(ObjectUtils.isEmpty(info)){
            throw new ServiceException("需求不存在");
        }
        if(!info.getDemandState().equals(DemandStateConstant.ACCEPT)){
            throw new ServiceException("当前需求不为待接收,无法接收");
        }
        //修改数据
        LambdaUpdateChainWrapper<DeDemandInfo> updateChainWrapper = lambdaUpdate()
                .eq(DeDemandInfo::getId, demandId)
                //设置需求负责人
                .set(DeDemandInfo::getDemandUser, SecurityUtils.getUserId());
        //判断是否是转交的需求
        if(!ObjectUtils.isEmpty(info.getTransferState())){
            //清空转交人,和转交前的状态
            updateChainWrapper.set(DeDemandInfo::getTransferState,null);
            updateChainWrapper.set(DeDemandInfo::getTransferUser,null);
            //设置状态为转交前的状态
            updateChainWrapper.set(DeDemandInfo::getDemandState,info.getTransferState());
        }else{
            //设置状态为待调研
            updateChainWrapper.set(DeDemandInfo::getDemandState,DemandStateConstant.RESEARCH);
        }
        //执行修改
        updateChainWrapper.update();
        //记录操作流程
        processService.saveProcess(demandId,DemandProcessConstant.ACCEPT,null);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void back(DemandOperDto dto) {
        //查询需求
        DeDemandInfo info = getById(dto.getId());
        if(ObjectUtils.isEmpty(info)){
            throw new ServiceException("需求不存在");
        }
        if(!info.getDemandState().equals(DemandStateConstant.ACCEPT)){
            throw new ServiceException("当前需求不为待接收,无法退回");
        }
        //todo 判断自己是分配人或者超级管理员
        //修改数据
        LambdaUpdateChainWrapper<DeDemandInfo> updateChainWrapper = lambdaUpdate()
                .eq(DeDemandInfo::getId, dto.getId());
        //判断是否是转交的需求
        if(!ObjectUtils.isEmpty(info.getTransferState())){
            //清空转交人,和转交前的状态
            updateChainWrapper.set(DeDemandInfo::getTransferState,null);
            updateChainWrapper.set(DeDemandInfo::getTransferUser,null);
            //设置状态为转交前的状态
            updateChainWrapper.set(DeDemandInfo::getDemandState,info.getTransferState());
            //设置需求负责人
            updateChainWrapper.set(DeDemandInfo::getDemandUser,info.getDemandUser());
        }else{
            //设置状态为待分配
            updateChainWrapper
                    .set(DeDemandInfo::getDemandState,DemandStateConstant.ALLOCATION)
                    .set(DeDemandInfo::getWaitAllocationTime,DateUtils.getNowDate());
        }
        //执行修改
        updateChainWrapper.update();
        //退回后需要删除分配数据
        allocationService.lambdaUpdate().eq(DeDemandAllocation::getDemandId,dto.getId()).remove();
        //记录操作流程
        processService.saveProcess(dto.getId(),DemandProcessConstant.BACK,dto);
    }

    @Override
    @DataScope(deptAlias = "ds")
    public List<DemandInfoPageVO> demandPage(DemandInfoPageDto dto, BasePage page) {
        if(!ObjectUtils.isEmpty(page)){
            PageUtils.startPage();
        }
        dto.setCurrentUser(SecurityUtils.getUserId());
        List<DemandInfoPageVO> demandInfoPageVOS = this.baseMapper.demandPage(dto);
        //查询用户是否坐席人员
        boolean seatNow = seatService.isSeatNow();
        demandInfoPageVOS.forEach(data->{
            data.setDemandEnclosureList(FileUtils.IdToFile(data.getDemandEnclosure()));
            data.setServerDesk(seatNow);
        });
        return ConversionUtil.conversionList(demandInfoPageVOS,DemandInfoPageVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void research(DemandResearchAddDto dto) {
        DeDemandInfo info = getById(dto.getDemandId());
        if(ObjectUtils.isEmpty(info)){
            throw new ServiceException("需求不存在");
        }
        if(!info.getDemandState().equals(DemandStateConstant.RESEARCH)){
            throw new ServiceException("当前不为待调研状态,无法调研");
        }
        if(!info.getDemandUser().equals(SecurityUtils.getUserId())&&!SecurityUtils.isAdmin()){
            throw new ServiceException("没有权限执行该需求的调研");
        }
        DeDemandResearch research = dto.buildResearch();
        researchService.save(research);
        //修改状态
        lambdaUpdate()
                .eq(DeDemandInfo::getId,dto.getDemandId())
                .set(DeDemandInfo::getDemandState,DemandStateConstant.ANALYZE)
                .update();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void transfer(TransferDto dto) {
        DeDemandInfo info = getById(dto.getId());
        if(ObjectUtils.isEmpty(info)){
            throw new ServiceException("需求不存在");
        }
        if(!Arrays.asList(DemandStateConstant.RESEARCH,DemandStateConstant.ANALYZE).contains(info.getDemandState())){
            throw new ServiceException("需求当前状态不能转交");
        }
        //修改需求状态,缓存转交信息
        lambdaUpdate()
                .eq(DeDemandInfo::getId,info.getId())
                .set(DeDemandInfo::getTransferState,info.getDemandState())
                .set(DeDemandInfo::getTransferUser,info.getDemandUser())
                .set(DeDemandInfo::getDemandUser,null)
                .set(DeDemandInfo::getDemandState,DemandStateConstant.ACCEPT)
                .set(DeDemandInfo::getWaitAcceptTime,DateUtils.getNowDate())
                .update();
        //新增分配需求,删除之前的分配信息
        allocationService.transferAllocation(dto);
        //添加转交记录
        processService.saveProcess(dto.getId(),DemandProcessConstant.TRANSFER,dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pause(DemandOperDto dto) {
        DeDemandInfo info = getById(dto.getId());
        if(ObjectUtils.isEmpty(info)){
            throw new ServiceException("需求不存在");
        }
        if(!Arrays.asList(DemandStateConstant.RESEARCH,DemandStateConstant.ANALYZE,DemandStateConstant.RATING).contains(info.getDemandState())){
            throw new ServiceException("需求当前状态不能暂停");
        }
        lambdaUpdate()
                .eq(DeDemandInfo::getId,info.getId())
                .set(DeDemandInfo::getPauseState,info.getDemandState())
                .set(DeDemandInfo::getDemandState,DemandStateConstant.PAUSE)
                .update();
        //todo 暂停该需求的下的任务 除了状态为“已暂停、已终止、已完成”的任务 并通知任务处理人
        taskInfoService.demandPause(dto);
        //添加暂停记录
        processService.saveProcess(dto.getId(),DemandProcessConstant.PAUSE,dto);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void open(SimpleDto<Long> dto) {
        DeDemandInfo info = getById(dto.getData());
        if(ObjectUtils.isEmpty(info)){
            throw new ServiceException("需求不存在");
        }
        if(!info.getDemandState().equals(DemandStateConstant.PAUSE)){
            throw new ServiceException("当前不为暂停状态,无法开启");
        }
        lambdaUpdate()
                .eq(DeDemandInfo::getId,info.getId())
                .set(DeDemandInfo::getPauseState,null)
                .set(DeDemandInfo::getDemandState,info.getPauseState())
                .update();
        //添加开启记录
        processService.saveProcess(dto.getData(),DemandProcessConstant.OPEN,null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void termination(DemandOperDto dto) {
        DeDemandInfo info = getById(dto.getId());
        if(ObjectUtils.isEmpty(info)){
            throw new ServiceException("需求不存在");
        }
        if(!Arrays.asList(DemandStateConstant.RESEARCH,DemandStateConstant.ANALYZE,DemandStateConstant.RATING,DemandStateConstant.PAUSE)
                .contains(info.getDemandState())){
            throw new ServiceException("需求当前状态不能终止");
        }
        lambdaUpdate()
                .eq(DeDemandInfo::getId,info.getId())
                .set(DeDemandInfo::getDemandState,DemandStateConstant.TERMINATION)
                .update();
        taskInfoService.demandTermination(dto);
        //添加暂停记录
        processService.saveProcess(dto.getId(),DemandProcessConstant.TERMINATION,dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void analyze(DemandAnalyzeAddDto dto) {
        DeDemandInfo info = getById(dto.getDemandId());
        if(ObjectUtils.isEmpty(info)){
            throw new ServiceException("需求不存在");
        }
        if(!DemandStateConstant.ANALYZE.equals(info.getDemandState())){
            throw new ServiceException("当前状态不为待需求分析,无法执行需求分析");
        }
        //判断需求是否存在可行性
        if(dto.getDemandFeasible().equals(0)||dto.getDemandRequired().equals(0)){
            //终止需求
            termination(new DemandOperDto(){{setId(dto.getDemandId());setReason("需求分析未通过");}});
        }else{
            //保存需求分析
            DeDemandAnalyze analyze = dto.buildAnalyze();
            analyzeService.save(analyze);
            //修改需求状态为待需求定性
            lambdaUpdate()
                    .eq(DeDemandInfo::getId,dto.getDemandId())
                    .set(DeDemandInfo::getDemandState,DemandStateConstant.RATING)
                    .update();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rating(DemandRatingAddDto dto) {
        DeDemandInfo info = getById(dto.getDemandId());
        if(ObjectUtils.isEmpty(info)){
            throw new ServiceException("需求不存在");
        }
        if(!DemandStateConstant.RATING.equals(info.getDemandState())){
            throw new ServiceException("当前状态不为待定级,无法执行需求定性");
        }
        if(dto.getRatingType().equals(RatingTypeConstant.OPTIMIZATION)){
            //系统升级优化
            DeDemandRating rating = dto.buildRating(null);
            ratingService.save(rating);
            //修改需求状态为处理中
            lambdaUpdate()
                    .eq(DeDemandInfo::getId,dto.getDemandId())
                    .set(DeDemandInfo::getDemandState,DemandStateConstant.PROCESSING)
                    .update();
        }
        else if(dto.getRatingType().equals(RatingTypeConstant.PROJECT)){
            //新建项目
            DeDemandProjectAudit audit = dto.buildAudit();
            projectAuditService.save(audit);
            DeDemandRating rating = dto.buildRating(audit.getId());
            ratingService.save(rating);
            //修改为转项目
            lambdaUpdate()
                    .eq(DeDemandInfo::getId,dto.getDemandId())
                    .set(DeDemandInfo::getDemandState,DemandStateConstant.PROJECT_AUDIT)
                    .update();
            //记录转项目
            processService.saveProcess(dto.getDemandId(),DemandProcessConstant.CONVERT_PROJECT,null);
        }
    }

    /**
     * 需求处理完成,任务终止原因
     */
    private static final String DEMAND_COMPLETED_REASON = "需求已处理完成";
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void make(DemandMakeDto dto) {
        DeDemandInfo info = getById(dto.getDemandId());
        if(ObjectUtils.isEmpty(info)){
            throw new ServiceException("当前需求不存在");
        }
        if(!DemandStateConstant.PROCESSING.equals(info.getDemandState())){
            throw new ServiceException("当前状态不为处理中,无法处理需求");
        }
        //判断进度是否为100
        if(dto.getMakeProcess().equals(100)){
            //检查当前需求下是否还有任务未完成
            taskInfoService
                    .lambdaQuery()
                    .eq(DeTaskInfo::getDemandId, dto.getDemandId())
                    .in(DeTaskInfo::getTaskState, Arrays.asList(TaskStateConstant.WAIT_ACCEPT, TaskStateConstant.PROCESSING, TaskStateConstant.PAUSE))
                    .list()
                    .stream()
                    .forEach(data->{
                        taskInfoService.termination(new DemandOperDto(){{setId(data.getId());setReason(DEMAND_COMPLETED_REASON);}});
                    });
            ;
            //修改状态为完成
            lambdaUpdate()
                    .eq(DeDemandInfo::getId,dto.getDemandId())
                    .set(DeDemandInfo::getDemandProcess,dto.getMakeProcess())
                    .set(DeDemandInfo::getDemandState,DemandStateConstant.COMPLETED)
                    .update();
            //处理完成
            processService.saveProcess(dto.getDemandId(),DemandProcessConstant.DONE,null);
        }else{
            //修改进度
            lambdaUpdate()
                    .eq(DeDemandInfo::getId,dto.getDemandId())
                    .set(DeDemandInfo::getDemandProcess,dto.getMakeProcess())
                    .update();
        }
        //保存处理内容
        DeDemandMake make = dto.buildMake();
        makeService.save(make);
    }

    @Override
    public DemandDetailVO getInfo(Long id) {
        DemandDetailVO vo = new DemandDetailVO();
        //查询需求
        vo.setInfo(getDemandInfo(id));
        //查询调研信息
        vo.setResearch(getResearchInfo(id));
        vo.setAnalyze(getAnalyzeInfo(id));
        vo.setRating(getRatingInfo(id));
        vo.setTaskList(getTaskInfo(id));
        vo.setMakeList(getMakeInfo(id));
        return vo;
    }

    private DemandInfoVO getDemandInfo(Long id){
        DeDemandInfo info = getById(id);
        DemandInfoVO demandInfoVO = new DemandInfoVO(info);
        demandInfoVO = ConversionUtil.conversion(demandInfoVO,DemandInfoVO.class);
        //查询提出科室
        List<DeDemandSub> list = deDemandSubService.lambdaQuery().eq(DeDemandSub::getDemandId, id).list();
        demandInfoVO.setSubInfo(ConversionUtil.conversionList(list.stream().map(data->new DemandInfoSubVO(data)).collect(Collectors.toList()),DemandInfoSubVO.class));
        return demandInfoVO;
    }

    private DemandResearchVO getResearchInfo(Long demandId){
        DeDemandResearch research = researchService
                .lambdaQuery()
                .eq(DeDemandResearch::getDemandId, demandId)
                .one();
        if(!ObjectUtils.isEmpty(research)){
            DemandResearchVO researchVO = ConversionUtil.conversion(new DemandResearchVO(research),DemandResearchVO.class);
            return researchVO;
        }
        return null;
    }

    private DemandAnalyzeVO getAnalyzeInfo(Long demandId){
        DeDemandAnalyze analyze = analyzeService
                .lambdaQuery()
                .eq(DeDemandAnalyze::getDemandId, demandId)
                .one();
        if(!ObjectUtils.isEmpty(analyze)){
            DemandAnalyzeVO analyzeVO = ConversionUtil.conversion(new DemandAnalyzeVO(analyze),DemandAnalyzeVO.class);
            return analyzeVO;
        }
        return null;
    }

    private DemandRatingVO getRatingInfo(Long demandId){
        //查询定级信息
        DeDemandRating rating = ratingService
                .lambdaQuery()
                .eq(DeDemandRating::getDemandId, demandId)
                .one();
        if(!ObjectUtils.isEmpty(rating)){
            //查询需求立项数据
            DeDemandProjectAudit audit = projectAuditService.lambdaQuery()
                    .eq(DeDemandProjectAudit::getDemandId, demandId)
                    .one();
            DemandRatingVO ratingVO = ConversionUtil.conversion(new DemandRatingVO(rating,audit),DemandRatingVO.class);
            return ratingVO;
        }
        return null;
    }

    @Override
    public List<DemandTaskVO> getTaskInfo(Long demandId){
        //查询任务信息
        List<DeTaskInfo> list = taskInfoService
                .lambdaQuery()
                .eq(DeTaskInfo::getDemandId, demandId)
                .list();
        if(!CollectionUtils.isEmpty(list)){
            return list.stream().map(data -> {
                //todo 判断是否退单
                DemandTaskVO demandTaskVO = ConversionUtil.conversion(new DemandTaskVO(data), DemandTaskVO.class);
                return demandTaskVO;
            }).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    @DataScope(deptAlias = "ds")
    public List<DemandTypeVO> getDemandType(DemandInfoPageDto dto) {
        List<SysDictData> dictCache = DictUtils.getDictCache(SysDictTypeConstant.DE_DEMAND_TYPE);
        dto.setCurrentUser(SecurityUtils.getUserId());
        dto.setKeyword(null);
        return dictCache.stream().map(data -> {
            DemandTypeVO vo = new DemandTypeVO(data);
            dto.setDemandType(data.getDictValue());
            vo.setCount(this.deDemandInfoMapper.demandPageCount(dto));
            return vo;
        }).collect(Collectors.toList());
    }

    private List<DemandMakeVO> getMakeInfo(Long demandId){
        //查询任务信息
        List<DeDemandMake> list = makeService
                .lambdaQuery()
                .eq(DeDemandMake::getDemandId, demandId)
                .orderByDesc(DeDemandMake::getId)
                .list();
        if(!CollectionUtils.isEmpty(list)){
            return list.stream().map(data -> {
                DemandMakeVO makeVO = ConversionUtil.conversion(new DemandMakeVO(data), DemandMakeVO.class);
                return makeVO;
            }).collect(Collectors.toList());
        }
        return null;
    }
}
